#ifndef __GACORE_H_
#define __GACORE_H_

#include "popolazione.hpp"
#include "Validator.hpp"
#include "GAmodSettings.hpp"

/** \class GAcoreException
 *  \brief Eccezioni lanciate dalla classe GAcore
 */
class GAcoreException : public EHW_Exception{
    public:
    /** Costruttore
     *  \sa EHW_Exception::EHW_Exception
     */
    GAcoreException(char *mess) : EHW_Exception(mess) {};
};

/** \class  GAcore
 *  \brief  Classe astratta che rappresenta un generico GA core.
 *
 *  Il GAcore e' il modulo del framework che implementa la fase di esecuzione dell'algoritmo evolutivo.
 */
class GAcore {
    protected:
    //!Validatore utilizzato per il calcolo del fitness
    Validator *myValidator;

    public:
    //! Comporamento a fronte di un parametro non specificato della loadSettings
    enum load_exc {
        THROW_EXCEPTION,    //!< In caso un parametro non sia specificato lancia un'eccezione
        IGNORE_PARAMETERS   //!< Ignora tutti i parametri non specificati
    };

    /** Costruttore base, "installa" il validator.
     *
     *  \param[in]  val         Validator da utilizzare
     *  \param[in]  settings    Lista di impostazioni
     */
    GAcore(Validator *val,GAmodSettings &settings) throw(GAcoreException)
    {
        if(!val)
        throw GAcoreException("GAcore::GAcore: validator non valido!");

        myValidator = val;
    }

    //! Restituisce il validator usato da questo core.
    Validator *getValidator() {return myValidator;}

    /** Questa metodo dovra' essere usata dal Controller per ottenere informazioni sull'andamento del processo evolutivo.
     *  Tutte le informazioni ritornate dipendono dall'implementazione del GAcore anche se sarebbe bene implementare alcuni
     *  parametri comuni per la lista di comandi (es. fitness massimo e medio...)
     *
     *  \param[out] settings    Contenitore nel quale saranno inseriti i parametri da ritornare
     *  \param[in]  lista       Lista di parametri da calcolare
     *
     *  \return                 Numero di parametri calcolati
     */
    virtual int getGenerationData(GAmodSettings &settings,HERAuint32 lista = 0) = 0;

    /** Questa metodo esegue \c num generazioni dell'algoritmo evolutivo
     *
     *  \param[in]  num Numero di generazioni da eseguire
     *  \return         Numero di generazioni eseguite
     */
    virtual int runGeneration(int num) = 0;

    /** Metodo usato per aggiornare i parametri del GAcore. Il numero e nome di parametri dipende dall'implementazione.
     *
     *  \param[in]  settings    Contiene i parametri da passare al GAcore
     *  \param[in]  le          Specifica il comportamento a fronte del mancato inserimento di un parametro
     *  \return                 Numero di parametri letti
     */
    virtual int loadSettings(GAmodSettings &settings,load_exc le = GAcore::THROW_EXCEPTION) throw(GAcoreException) = 0;

    /** Restituisce una copia della popolazione attuale
     *
     *  \param[out] p   Popolazione nella quale verra' copiata quella attuale
     */
    virtual void getPopolazione(Popolazione &p) = 0;
};

#endif
